#include"index.hpp"
#include"util.hpp"
#include<algorithm>
#include<unordered_map>
#include<jsoncpp/json/json.h>

namespace ns_searcher
{
  struct InvertedElemPrint
  {
    uint64_t doc_id;
    int weight;
    std::vector<std::string> words;
    InvertedElemPrint():doc_id(0),weight(0){}
  };

  class Searcher
  {
    private:
      ns_index::Index * index;//供系统进行查找的索引
    public:
      Searcher(){}
      ~Searcher(){}
    public:
      void InitSearcher(const std::string &input)
      {
        //1.获取或创建index对象
        index = ns_index::Index::GetInstance();
        //std::cout<<"获取index单例成功"<<std::endl;
        LOG(NORMAL, "获取index单例成功...");
        //2.根据index对象建立索引
        index->BuildIndex(input);
        //std::cout<<"建立正排和倒排索引成功..."<<std::endl;
        LOG(NORMAL, "建立正排和倒排索引成功...");
      }
      
        //query:搜索关键字
        //json:返回给用户浏览器的搜索结果
        void Search(const std::string &query, std::string *json_string)
        {
          //1.[分词]:对我们的query进行按照searcher的要求进行分词
          std::vector<std::string> words;
          ns_util::JiebaUtil::CutString(query,&words);
          //2.[触发]:根据分词的各个词进行index查找，建立index
          //ns_index::InvertedList inverted_list_all;
          std::vector<InvertedElemPrint> inverted_list_all;

          std::unordered_map<uint64_t,InvertedElemPrint> tokens_map;

          for(std::string word : words)
          {
            boost::to_lower(word);

            ns_index::InvertedList * inverted_list = index->GetInvertedList(word);
            if(inverted_list == nullptr)
            {
              continue;
            }
            //inverted_list_all.insert(inverted_list_all.end(),inverted_list->begin(),inverted_list->end());
            for(const auto &elem : *inverted_list)
            {
              auto &item = tokens_map[elem.doc_id];
              item.doc_id = elem.doc_id;
              item.weight += elem.weight;
              item.words.push_back(elem.word);
            }
          }
          for(const auto &item:tokens_map)
          {
            inverted_list_all.push_back(std::move(item.second));
          }
            //3.[合并排序]:汇总查找结果，按照相关性(weight)降序排序
            // std::sort(inverted_list_all.begin(),inverted_list_all.end(),[](const ns_index::InvertedElem &e1,const ns_index::InvertedElem &e2)
            //     {
            //     return e1.weight > e2.weight;
            //     });
            std::sort(inverted_list_all.begin(), inverted_list_all.end(),
                          [](const InvertedElemPrint &e1, const InvertedElemPrint &e2){
                          return e1.weight > e2.weight;
                          });
            //4.[构建]:根据查找结果，构建json串
            Json::Value root;
            for(auto &item :inverted_list_all)
            {
              ns_index::DocInfo* doc = index->GetForwardIndex(item.doc_id);
              if(doc == nullptr)
              {
                continue;
              }
              Json::Value elem;
              elem["title"] = doc->title;
              elem["desc"] =GetDesc(doc->content,item.words[0]);//word为关键字
              elem["url"] = doc->url;

              elem["id"] = (int)item.doc_id;//类型不匹配
              elem["weight"] = item.weight;

              root.append(elem);
            }
            Json::StyledWriter writer;
        
            *json_string = writer.write(root);
        }
       //提取摘要 
        std::string GetDesc(const std::string &html_content,const std::string &word)
        {
          const int prev_step = 50;
          const int next_step = 100;
          //1.找到首次出现
          auto iter = std::search(html_content.begin(),html_content.end(),word.begin(),word.end(),[](int x,int y)
              {
                return (std::tolower(x) == std::tolower(y));
              });
          if(iter == html_content.end())
          {
            return "None1";
          }
          int pos = std::distance(html_content.begin(),iter);//获取begin()到iter之间的元素个数
          //2.获取start,end
          int start = 0;
          int end = html_content.size()-1;
          if(pos > start+prev_step) start = pos - prev_step;//注意类型为unsingend,需要调换一下prev_step
          if(pos <end-next_step) end = pos+next_step;//注意防止pos+next_step越界需要强转+换位
          if(start >= end) return "None2";
          std::string desc = html_content.substr(start,end-start);
          desc += "...";
          return desc;
        }

  };
}
